<template>
  <!-- 使用 ElInputNumber，以 formatter / parser 保证在输入时就显示固定小数位 -->

  <!-- :formatter="formatToFixed" 决定输入框中如何显示（保持 trailing zeros） -->
  <!-- :parser="parseNumber" 决定字符串怎样转成内部 numeric -->
  <!-- :controls="true"  是否显示 + / - 按钮 -->
  <!-- @blur="handleBlur"  仅在失焦时将结果更新给父组件 -->
  <!-- :step="stepValue" 根据 precision 动态决定步长 -->
  <el-input-number
    v-model="internalNumber"
    :formatter="formatToFixed"
    :parser="parseNumber"
    :min="min"
    :max="max"
    :disabled="disabled"
    :step="stepValue"
    :controls="true"
    :placeholder="placeholder"
    :controls-position="controlsPosition"
    :size="size"
    @blur="handleBlur"
    @change="handleChange"
    @focus="$emit('focus', $event)"
  >
    <!-- 添加前缀插槽 -->
    <template #prefix v-if="$slots.prefix">
      <slot name="prefix"></slot>
    </template>
    
    <!-- 添加后缀插槽 -->
    <template #suffix v-if="$slots.suffix">
      <slot name="suffix"></slot>
    </template>

    <!-- 添加增加/减少按钮的自定义图标插槽 -->
    <template #increase-icon v-if="$slots['increase-icon']">
      <slot name="increase-icon"></slot>
    </template>
    
    <template #decrease-icon v-if="$slots['decrease-icon']">
      <slot name="decrease-icon"></slot>
    </template>
  </el-input-number>
</template>

<script setup lang="ts">
  import { ref, watch, computed } from 'vue'
  import { ElMessage } from 'element-plus'

  const props = defineProps({
    modelValue: {
      type: Number,
      default: 0, // 外部传入的值(单位：分)
    },
    precision: {
      type: Number,
      default: 2, // 显示/计算时小数位个数
    },
    placeholder: {
      type: String,
      default: '请输入金额',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    min: {
      type: Number,
      // default: Number.MIN_SAFE_INTEGER,
      default: 0,
    },
    max: {
      type: Number,
      default: Number.MAX_SAFE_INTEGER,
    },
    controlsPosition: {
      type: String,
      default: undefined, // 可以是 'right' 或不设置
    },
    size: {
      type: String,
      default: 'default', // 可选值: 'large', 'default', 'small'
    },
  })

  const emits = defineEmits([
    'update:modelValue',
    'focus',  // 添加focus事件支持
    'change', // 显式声明change事件
    'blur'    // 显式声明blur事件
  ])

  // internalNumber：组件内的数值(单位：元)
  const internalNumber = ref<number>(0)

  // 初始化(将分 => 元)
  internalNumber.value = props.modelValue / Math.pow(10, props.precision)

  // 如果父组件的值改变，也要同步更新 internalNumber
  watch(
    () => props.modelValue,
    (newVal) => {
      if (typeof newVal === 'number' && !isNaN(newVal)) {
        internalNumber.value = newVal / Math.pow(10, props.precision)
      } else {
        internalNumber.value = 0
      }
    },
  )

  // 根据 precision 计算步长，如 precision=1 => 0.1, precision=2 => 0.01
  const stepValue = computed(() => {
    return 1 / Math.pow(10, props.precision)
  })

  // 当输入框失焦时更新父组件
  const handleBlur = () => {
    convertAndEmit()
  }

  // 当点击 + / - 改变值时，立即更新父组件
  const handleChange = () => {
    convertAndEmit()
  }

  // “元” => “分”并 emit
  function convertAndEmit() {
    let val = parseFloat(internalNumber.value + '')
    if (isNaN(val)) {
      ElMessage.error('请输入正确的金额')
      internalNumber.value = props.modelValue / Math.pow(10, props.precision)
      return
    }
    // 先四舍五入到 precision，再乘以 10^precision 得到“分”
    val = parseFloat(val.toFixed(props.precision))
    const actualValue = Math.round(val * Math.pow(10, props.precision))
    emits('update:modelValue', actualValue)

    // 同步 internalNumber，防止用户手工输入导致小数位和实际值不一致
    internalNumber.value = actualValue / Math.pow(10, props.precision)
  }

  /**
   * formatter：决定输入框内的展示(带有 precision 位小数)
   */
  function formatToFixed(value: number | string): string {
    const numVal = parseFloat(value + '')
    if (Number.isNaN(numVal)) return ''
    return numVal.toFixed(props.precision)
  }

  /**
   * parser：决定如何将输入框的字符串解析为数字
   */
  function parseNumber(value: string): number {
    const val = parseFloat(value)
    if (Number.isNaN(val)) return 0
    return val
  }
</script>
